/*
 * Copyright 2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { cart, order, security } from "@mall/api-services"
import * as _ from "lodash"
import { observable } from "mobx"
import { observer } from "mobx-react"
import * as React from "react"
import { RouteComponentProps, withRouter } from "react-router"
import Button from "../components/button"
import Checkbox from "../components/checkbox"
import Flex from "../components/flex"
import ProductPrice from "../components/product/product-price"
import session, { FILL_ORDERS_NAME } from "../session"
import "./index.scss"
import * as state from "./state"

import StoreGroupedCartItems from "./store-grouped-cart-items"

interface CartProps extends RouteComponentProps {
}

interface CartState {
  items: cart.CartItem[];
  manageVisible: boolean;
}

@observer
class Cart extends React.Component<CartProps, CartState> {

  public constructor(props: CartProps) {
    super(props)

    this.state = {
      items: [],
      manageVisible: false,
    }

    this.handleDeleteItems = this.handleDeleteItems.bind(this)
    this.handleCheckout = this.handleCheckout.bind(this)
  }

  @observable
  private cart: state.Cart = new state.Cart()

  public componentDidMount(): void {
    this.refreshCart()
  }

  public render() {
    const groupedItems = this.getGroupedItems()
    const { items, manageVisible } = this.state
    const { cart } = this
    return (
      <>
        <div className="shopping-cart">
          <div className="shopping-cart-content">
            <div className="shopping-cart-topbar">
              <div className="shopping-cart-title">
                <span>购物车</span>
                <span className="shopping-cart-title-right"
                      onClick={() => this.setState({ manageVisible: !manageVisible })}
                >{manageVisible ? "完成" : "管理"}</span>
              </div>
              <div className="shopping-cart-count">共{items.length}件宝贝</div>
            </div>
            <div>
              {_.map(groupedItems, aItems =>
                <StoreGroupedCartItems key={aItems.storeId}
                                       cart={this.cart}
                                       storeId={aItems.storeId}
                                       items={aItems.items}/>)}
            </div>
          </div>
          <div className="shopping-cart-actions">
            <Checkbox className="cart-item-checkbox"
                      checked={!_.isEmpty(items) && cart.containsAll(items)}
                      onChange={e => {
                        e.stopPropagation()
                        if (e.target.checked) {
                          cart.addAll(items)
                        } else {
                          cart.removeAll(items)
                        }
                      }}><span
              style={{ marginLeft: "10px" }}>全选</span></Checkbox> {manageVisible ?
            <Button className="shopping-cart-manage-delete-button" shape="circle"
                    onClick={this.handleDeleteItems}>删除</Button> :
            <Flex alignItems="center">
              <Flex className="shopping-cart-total-amount">
                <span>合计: </span>
                <ProductPrice price={cart.totalAmount} size={16}/>
              </Flex>
              <Button className="shopping-to-pay-button" shape="circle"
                      onClick={this.handleCheckout}>
                去结算({cart.count})
              </Button>
            </Flex>}
          </div>
        </div>
      </>
    )
  }

  public getGroupedItems(): { storeId: string, items: cart.CartItem[] }[] {
    const { items } = this.state
    const storeGroupedItems = _.groupBy(items, item => item.storeId)
    const groupedItems: { storeId: string, items: cart.CartItem[] }[] = []
    _.forIn(storeGroupedItems, (aItems: cart.CartItem[], storeId: string) => {
      groupedItems.push({
        storeId,
        items: aItems,
      })
    })
    return groupedItems
  }

  private readonly handleDeleteItems = () => {
    const items = this.cart.getItems()
    const variantIds = _.map(items, item => item.variantId)
    if (!_.isEmpty(variantIds)) {
      cart.CartServiceV1
        .removeCartItems(security.SecurityUserHolder.getUserId(), variantIds)
        .then(() => this.cart.removeAll(items))
        .then(() => this.refreshCart())
    }
  }

  private readonly handleCheckout = () => {
    const orders = _.chain(this.cart.getItems())
      .map(cartItem => _.assign(new order.OrderItem(), cartItem))
      .groupBy(item => item.storeId)
      .map(items => {
        const newOrder = new order.Order()
        newOrder.items = items
        newOrder.storeId = _.first(items)?.storeId as string
        return newOrder
      })
      .value()
    session.set(FILL_ORDERS_NAME, orders)
    this.props.history.push("/orders/fill")
  }

  private readonly refreshCart = () => {
    cart.CartServiceV1
      .getCart(security.SecurityUserHolder.getUserId())
      .then(({ items }) => this.setState({ items }))
  }
}

export default withRouter(Cart)
